package com.example.my_helper;

import android.graphics.Color;
import android.os.Handler;
import android.text.Spannable;
import android.text.style.ForegroundColorSpan;

import java.util.Arrays;
import java.util.Date;

import com.example.my_helper.modbus4j.ip.IpParameters;
import com.serotonin.io.serial.SerialParameters;
import com.example.my_helper.modbus4j.ModbusFactory;
import com.example.my_helper.modbus4j.ModbusMaster;
import com.example.my_helper.modbus4j.exception.ModbusInitException;
import com.example.my_helper.modbus4j.exception.ModbusTransportException;
import com.example.my_helper.modbus4j.ip.IpParameters;
import com.example.my_helper.modbus4j.msg.ReadCoilsRequest;
import com.example.my_helper.modbus4j.msg.ReadCoilsResponse;
import com.example.my_helper.modbus4j.msg.ReadDiscreteInputsRequest;
import com.example.my_helper.modbus4j.msg.ReadDiscreteInputsResponse;
import com.example.my_helper.modbus4j.msg.ReadExceptionStatusRequest;
import com.example.my_helper.modbus4j.msg.ReadExceptionStatusResponse;
import com.example.my_helper.modbus4j.msg.ReadHoldingRegistersRequest;
import com.example.my_helper.modbus4j.msg.ReadHoldingRegistersResponse;
import com.example.my_helper.modbus4j.msg.ReadInputRegistersRequest;
import com.example.my_helper.modbus4j.msg.ReadInputRegistersResponse;
import com.example.my_helper.modbus4j.msg.ReportSlaveIdRequest;
import com.example.my_helper.modbus4j.msg.ReportSlaveIdResponse;
import com.example.my_helper.modbus4j.msg.WriteCoilRequest;
import com.example.my_helper.modbus4j.msg.WriteCoilResponse;
import com.example.my_helper.modbus4j.msg.WriteCoilsRequest;
import com.example.my_helper.modbus4j.msg.WriteCoilsResponse;
import com.example.my_helper.modbus4j.msg.WriteMaskRegisterRequest;
import com.example.my_helper.modbus4j.msg.WriteMaskRegisterResponse;
import com.example.my_helper.modbus4j.msg.WriteRegisterRequest;
import com.example.my_helper.modbus4j.msg.WriteRegisterResponse;
import com.example.my_helper.modbus4j.msg.WriteRegistersRequest;
import com.example.my_helper.modbus4j.msg.WriteRegistersResponse;

public class MyModbusMaster {

    final static int ON_CONNECT = 0;
    final static int ON_MESSAGE = 1;
    final static int ON_SEND = 2;
    final static int ON_CLOSE = 3;
    final static int ON_ERROR = 4;
    final static int NOT_FOUND = 5;
    final static int NO_PERMISSION = 6;
    final static int CONFIG_ERROR = 7;
    final static int UNSUPPORT = 8;
    final static int CONSOLE_LOG = 9;
    final static int CONSOLE_REFRESH = 10;
    final static int SEND_DATA = 11;

    ModbusDebuger parent;
    Handler handler;

    ModbusMaster master;
    boolean inited = false;
    int Mode = 0;
    boolean lock = false;

    public MyModbusMaster(ModbusDebuger parent, Handler handler){
        this.parent = parent;
        this.handler = handler;
    }

    public void Init(int mode, String host, int port) {
        if(inited)
            return;
        if(lock)
            return;
        lock = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                IpParameters ipParameters = new IpParameters();
                ipParameters.setHost(host);
                ipParameters.setPort(port);
                ModbusFactory modbusFactory = new ModbusFactory();
                if(mode == 2){
                    master = modbusFactory.createTcpMaster(ipParameters, false);
                }else if(mode == 3) {
                    master = modbusFactory.createTcpMaster(ipParameters, true);
                }else{
                    master = modbusFactory.createUdpMaster(ipParameters);
                }
                try {
                    master.init();
                    Mode = mode;
                    inited = true;
                    handler.sendEmptyMessage(ON_CONNECT);
                } catch (ModbusInitException e) {
                    e.printStackTrace();
                    handler.sendEmptyMessage(ON_ERROR);
                }
                lock = false;
            }
        }).start();

    }

    public void Init(int mode, int baudrate) {
        if(inited)
            return;
        SerialParameters serialParameters = new SerialParameters();
        serialParameters.setCommPortId("COM1");
        serialParameters.setPortOwnerName("Numb nuts");
        serialParameters.setBaudRate(baudrate);
        ModbusFactory modbusFactory = new ModbusFactory();
        if(mode == 0){
            master = modbusFactory.createRtuMaster(serialParameters);
        }else if(mode == 1){
            master = modbusFactory.createAsciiMaster(serialParameters);
        }else{
            handler.sendEmptyMessage(ON_ERROR);
            return;
        }
        try{
            master.init();
            Mode = mode;
            inited = true;
            handler.sendEmptyMessage(ON_CONNECT);
        }catch (Exception e){
            e.printStackTrace();
            //handler.sendEmptyMessage(ON_ERROR);
            parent.Log_i(e.toString());
        }

    }

    public void Unint(){
        if(inited) {
            master.destroy();
            inited = false;
        }
        //handler.sendEmptyMessage(ON_CLOSE);
    }


    public void readCoil(int slaveId, int start, int len) {
        try {
            ReadCoilsRequest request = new ReadCoilsRequest(slaveId, start, len);
            ReadCoilsResponse response = (ReadCoilsResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println(Arrays.toString(response.getBooleanData()));
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public void readDiscreteInput(int slaveId, int start, int len) {
        try {
            ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, start, len);
            ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println(Arrays.toString(response.getBooleanData()));
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public short[] readHoldingRegisters(int slaveId, int start, int len) {
        try {
            ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len);
            ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                return response.getShortData();
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
        return null;
    }

    public short[] readInputRegisters(int slaveId, int start, int len) {
        try {
            ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, start, len);
            ReadInputRegistersResponse response = (ReadInputRegistersResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                return response.getShortData();
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void writeCoil(int slaveId, int offset, boolean value) {
        try {
            WriteCoilRequest request = new WriteCoilRequest(slaveId, offset, value);
            WriteCoilResponse response = (WriteCoilResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println("Success");
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public void writeRegister(int slaveId, int offset, int value) {
        try {
            WriteRegisterRequest request = new WriteRegisterRequest(slaveId, offset, value);
            WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println("Success");
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public void readExceptionStatus(int slaveId) {
        try {
            ReadExceptionStatusRequest request = new ReadExceptionStatusRequest(slaveId);
            ReadExceptionStatusResponse response = (ReadExceptionStatusResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println(response.getExceptionStatus());
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public void reportSlaveId(int slaveId) {
        try {
            ReportSlaveIdRequest request = new ReportSlaveIdRequest(slaveId);
            ReportSlaveIdResponse response = (ReportSlaveIdResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println(Arrays.toString(response.getData()));
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public void writeCoils(int slaveId, int start, boolean[] values) {
        try {
            WriteCoilsRequest request = new WriteCoilsRequest(slaveId, start, values);
            WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println("Success");
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public void writeRegisters(int slaveId, int start, short[] values) {
        try {
            WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);
            WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println("Success");
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    public void writeMaskRegister(int slaveId, int offset, int and, int or) {
        try {
            WriteMaskRegisterRequest request = new WriteMaskRegisterRequest(slaveId, offset, and, or);
            WriteMaskRegisterResponse response = (WriteMaskRegisterResponse) master.send(request);

            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println("Success");
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

}
